# -*- coding: utf-8 -*-
"""
按钮组件
实现基础按钮绘制、鼠标悬停效果、点击反馈动画和回调机制
"""

import pygame
import time
from typing import Optional, Callable
from gui.components.base_component import BaseComponent
from gui.styles.colors import get_current_theme
from gui.styles.fonts import get_font, render_text


class Button(BaseComponent):
    """
    按钮组件
    支持文本显示、鼠标悬停效果、点击动画和回调函数
    """
    
    def __init__(self, x: int, y: int, width: int, height: int, 
                 text: str = "", font_name: str = "button"):
        """
        初始化按钮
        
        Args:
            x (int): X坐标
            y (int): Y坐标
            width (int): 宽度
            height (int): 高度
            text (str): 按钮文本
            font_name (str): 字体名称
        """
        super().__init__(x, y, width, height)
        
        # 文本相关属性
        self.text = text
        self.font = get_font(font_name)
        
        # 状态相关属性
        self.pressed = False
        self.press_time = 0
        self.press_duration = 0.1  # 按下动画持续时间（秒）
        
        # 样式相关属性
        self.border_radius = 4
        self.padding = 8
        
        # 动画相关属性
        self.hover_animation_progress = 0.0
        self.hover_animation_speed = 8.0  # 悬停动画速度
        
        # 按钮类型
        self.button_type = "primary"  # primary, secondary, danger, success
        
        # 图标支持（可选）
        self.icon: Optional[pygame.Surface] = None
        self.icon_position = "left"  # left, right, top, bottom
        self.icon_spacing = 4
    
    def set_text(self, text: str):
        """设置按钮文本"""
        self.text = text
    
    def get_text(self) -> str:
        """获取按钮文本"""
        return self.text
    
    def set_button_type(self, button_type: str):
        """设置按钮类型
        
        Args:
            button_type (str): 按钮类型 (primary, secondary, danger, success)
        """
        if button_type in ["primary", "secondary", "danger", "success"]:
            self.button_type = button_type
    
    def set_icon(self, icon: pygame.Surface, position: str = "left"):
        """设置按钮图标
        
        Args:
            icon (pygame.Surface): 图标表面
            position (str): 图标位置 (left, right, top, bottom)
        """
        self.icon = icon
        if position in ["left", "right", "top", "bottom"]:
            self.icon_position = position
    
    def remove_icon(self):
        """移除按钮图标"""
        self.icon = None
    
    def _get_button_colors(self) -> dict:
        """根据按钮类型和状态获取颜色"""
        theme = get_current_theme()
        
        # 基础颜色配置
        color_configs = {
            "primary": {
                "normal": theme['accent'],
                "hover": self._darken_color(theme['accent'], 0.1),
                "pressed": self._darken_color(theme['accent'], 0.2),
                "disabled": theme['text_secondary'],
                "text": (255, 255, 255)
            },
            "secondary": {
                "normal": theme['panel_bg'],
                "hover": self._darken_color(theme['panel_bg'], 0.05),
                "pressed": self._darken_color(theme['panel_bg'], 0.1),
                "disabled": theme['text_secondary'],
                "text": theme['text_primary']
            },
            "danger": {
                "normal": theme['error'],
                "hover": self._darken_color(theme['error'], 0.1),
                "pressed": self._darken_color(theme['error'], 0.2),
                "disabled": theme['text_secondary'],
                "text": (255, 255, 255)
            },
            "success": {
                "normal": theme['success'],
                "hover": self._darken_color(theme['success'], 0.1),
                "pressed": self._darken_color(theme['success'], 0.2),
                "disabled": theme['text_secondary'],
                "text": (255, 255, 255)
            }
        }
        
        return color_configs.get(self.button_type, color_configs["primary"])
    
    def _darken_color(self, color: tuple, factor: float) -> tuple:
        """使颜色变暗
        
        Args:
            color (tuple): RGB颜色值
            factor (float): 变暗因子 (0-1)
            
        Returns:
            tuple: 变暗后的RGB颜色值
        """
        return tuple(max(0, int(c * (1 - factor))) for c in color)
    
    def _lighten_color(self, color: tuple, factor: float) -> tuple:
        """使颜色变亮
        
        Args:
            color (tuple): RGB颜色值
            factor (float): 变亮因子 (0-1)
            
        Returns:
            tuple: 变亮后的RGB颜色值
        """
        return tuple(min(255, int(c + (255 - c) * factor)) for c in color)
    
    def _interpolate_color(self, color1: tuple, color2: tuple, t: float) -> tuple:
        """在两个颜色之间插值
        
        Args:
            color1 (tuple): 起始颜色
            color2 (tuple): 结束颜色
            t (float): 插值参数 (0-1)
            
        Returns:
            tuple: 插值后的颜色
        """
        return tuple(int(c1 + (c2 - c1) * t) for c1, c2 in zip(color1, color2))
    
    def handle_event(self, event: pygame.event.Event) -> bool:
        """处理事件"""
        if not self.visible or not self.enabled:
            return False
        
        # 处理鼠标按下事件
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # 左键
                if self.contains_point(event.pos[0], event.pos[1]):
                    self.pressed = True
                    self.press_time = time.time()
                    return True
        
        # 处理鼠标释放事件
        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1 and self.pressed:
                self.pressed = False
                # 检查是否在按钮范围内释放
                if self.contains_point(event.pos[0], event.pos[1]):
                    if self.on_click:
                        self.on_click()
                return True
        
        # 处理鼠标移动事件
        elif event.type == pygame.MOUSEMOTION:
            is_hovering = self.contains_point(event.pos[0], event.pos[1])
            self.set_hover(is_hovering)
            
            # 如果鼠标移出按钮区域，取消按下状态
            if self.pressed and not is_hovering:
                self.pressed = False
        
        return False
    
    def update(self, dt: float):
        """更新按钮状态"""
        super().update(dt)
        
        # 更新悬停动画
        target_progress = 1.0 if self.hovered else 0.0
        if self.hover_animation_progress != target_progress:
            direction = 1 if target_progress > self.hover_animation_progress else -1
            self.hover_animation_progress += direction * self.hover_animation_speed * dt
            self.hover_animation_progress = max(0.0, min(1.0, self.hover_animation_progress))
        
        # 更新按下动画
        if self.pressed:
            current_time = time.time()
            if current_time - self.press_time > self.press_duration:
                self.pressed = False
    
    def draw(self, surface: pygame.Surface):
        """绘制按钮"""
        if not self.visible:
            return
        
        colors = self._get_button_colors()
        
        # 确定当前背景颜色
        if not self.enabled:
            bg_color = colors["disabled"]
            text_color = colors["text"]
        elif self.pressed:
            bg_color = colors["pressed"]
            text_color = colors["text"]
        else:
            # 使用悬停动画插值
            normal_color = colors["normal"]
            hover_color = colors["hover"]
            bg_color = self._interpolate_color(normal_color, hover_color, self.hover_animation_progress)
            text_color = colors["text"]
        
        # 计算按钮矩形（按下时稍微偏移）
        button_rect = self.rect.copy()
        if self.pressed:
            button_rect.x += 1
            button_rect.y += 1
        
        # 绘制按钮背景
        if self.border_radius > 0:
            self._draw_rounded_rect(surface, button_rect, bg_color, self.border_radius)
        else:
            pygame.draw.rect(surface, bg_color, button_rect)
        
        # 绘制边框（仅对secondary类型）
        if self.button_type == "secondary":
            border_color = colors["text"] if self.enabled else colors["disabled"]
            if self.border_radius > 0:
                self._draw_rounded_rect(surface, button_rect, border_color, self.border_radius, 1)
            else:
                pygame.draw.rect(surface, border_color, button_rect, 1)
        
        # 绘制内容（文本和图标）
        self._draw_content(surface, button_rect, text_color)
    
    def _draw_rounded_rect(self, surface: pygame.Surface, rect: pygame.Rect, 
                          color: tuple, radius: int, width: int = 0):
        """绘制圆角矩形"""
        if radius <= 0:
            pygame.draw.rect(surface, color, rect, width)
            return
        
        # 简化的圆角矩形绘制
        if width == 0:
            # 填充矩形
            pygame.draw.rect(surface, color, rect)
            # 这里可以添加更复杂的圆角绘制逻辑
        else:
            # 边框矩形
            pygame.draw.rect(surface, color, rect, width)
    
    def _draw_content(self, surface: pygame.Surface, button_rect: pygame.Rect, text_color: tuple):
        """绘制按钮内容（文本和图标）"""
        if not self.text and not self.icon:
            return
        
        # 计算内容区域
        content_rect = pygame.Rect(
            button_rect.x + self.padding,
            button_rect.y + self.padding,
            button_rect.width - 2 * self.padding,
            button_rect.height - 2 * self.padding
        )
        
        # 只有文本
        if self.text and not self.icon:
            self._draw_text_only(surface, content_rect, text_color)
        
        # 只有图标
        elif self.icon and not self.text:
            self._draw_icon_only(surface, content_rect)
        
        # 文本和图标都有
        elif self.text and self.icon:
            self._draw_text_and_icon(surface, content_rect, text_color)
    
    def _draw_text_only(self, surface: pygame.Surface, content_rect: pygame.Rect, text_color: tuple):
        """绘制纯文本"""
        text_surface = self.font.render(self.text, True, text_color)
        text_rect = text_surface.get_rect(center=content_rect.center)
        surface.blit(text_surface, text_rect)
    
    def _draw_icon_only(self, surface: pygame.Surface, content_rect: pygame.Rect):
        """绘制纯图标"""
        icon_rect = self.icon.get_rect(center=content_rect.center)
        surface.blit(self.icon, icon_rect)
    
    def _draw_text_and_icon(self, surface: pygame.Surface, content_rect: pygame.Rect, text_color: tuple):
        """绘制文本和图标"""
        text_surface = self.font.render(self.text, True, text_color)
        
        if self.icon_position in ["left", "right"]:
            # 水平布局
            total_width = text_surface.get_width() + self.icon.get_width() + self.icon_spacing
            start_x = content_rect.centerx - total_width // 2
            
            if self.icon_position == "left":
                # 图标在左
                icon_x = start_x
                text_x = start_x + self.icon.get_width() + self.icon_spacing
            else:
                # 图标在右
                text_x = start_x
                icon_x = start_x + text_surface.get_width() + self.icon_spacing
            
            # 垂直居中
            icon_y = content_rect.centery - self.icon.get_height() // 2
            text_y = content_rect.centery - text_surface.get_height() // 2
            
            surface.blit(self.icon, (icon_x, icon_y))
            surface.blit(text_surface, (text_x, text_y))
        
        else:
            # 垂直布局
            total_height = text_surface.get_height() + self.icon.get_height() + self.icon_spacing
            start_y = content_rect.centery - total_height // 2
            
            if self.icon_position == "top":
                # 图标在上
                icon_y = start_y
                text_y = start_y + self.icon.get_height() + self.icon_spacing
            else:
                # 图标在下
                text_y = start_y
                icon_y = start_y + text_surface.get_height() + self.icon_spacing
            
            # 水平居中
            icon_x = content_rect.centerx - self.icon.get_width() // 2
            text_x = content_rect.centerx - text_surface.get_width() // 2
            
            surface.blit(self.icon, (icon_x, icon_y))
            surface.blit(text_surface, (text_x, text_y))


class IconButton(Button):
    """
    图标按钮
    专门用于显示图标的按钮
    """
    
    def __init__(self, x: int, y: int, size: int, icon: pygame.Surface):
        """
        初始化图标按钮
        
        Args:
            x (int): X坐标
            y (int): Y坐标
            size (int): 按钮大小（正方形）
            icon (pygame.Surface): 图标表面
        """
        super().__init__(x, y, size, size, "")
        self.set_icon(icon)
        self.border_radius = size // 2  # 圆形按钮
        self.padding = 4


class ToggleButton(Button):
    """
    切换按钮
    可以在两个状态之间切换
    """
    
    def __init__(self, x: int, y: int, width: int, height: int, 
                 text_on: str = "ON", text_off: str = "OFF"):
        """
        初始化切换按钮
        
        Args:
            x (int): X坐标
            y (int): Y坐标
            width (int): 宽度
            height (int): 高度
            text_on (str): 开启状态文本
            text_off (str): 关闭状态文本
        """
        super().__init__(x, y, width, height, text_off)
        
        self.is_toggled = False
        self.text_on = text_on
        self.text_off = text_off
        
        # 重写点击回调
        self.on_toggle: Optional[Callable[[bool], None]] = None
        self.original_on_click = self.on_click
        self.on_click = self._handle_toggle
    
    def _handle_toggle(self):
        """处理切换逻辑"""
        self.toggle()
        if self.on_toggle:
            self.on_toggle(self.is_toggled)
        if self.original_on_click:
            self.original_on_click()
    
    def toggle(self):
        """切换状态"""
        self.is_toggled = not self.is_toggled
        self.text = self.text_on if self.is_toggled else self.text_off
        self.button_type = "success" if self.is_toggled else "secondary"
    
    def set_toggled(self, toggled: bool):
        """设置切换状态"""
        if self.is_toggled != toggled:
            self.toggle()